﻿using CrawlerFramework.ConfigEntity;
using CrawlerFramework.CrawlerEngine;
using CrawlerFramework.DataConverter;
using CrawlerFramework.Models;
using CrawlerFramework.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace CrawlerFramework.PageProcessor
{
    public abstract class PageProcessor
    {
        public EventWaitHandle DoneEvent { get; set; }

        //public ScheduledJob Job { get; set; }
              
        public Link Link { get; private set; }

        public LinkConfig LinkConfig { get; set; }

        public ILogService Logger { get; set; }

        public ICrawlerEngine CrawlerEngine { get; set; }
              
        public abstract CrawlStatus Execute();

        public PageProcessor(LinkConfig linkConfig, Link link)
        {
            this.Link = link;
            this.LinkConfig = linkConfig;
        }

        /// <summary>
        /// Convert data of 
        /// </summary>
        /// <param name="ids">Collection of ids that the data-converter will use to convert</param>
        /// <param name="dataConverters"></param>
        protected virtual void ConvertData(IEnumerable<int> ids, params IDataConverter[] dataConverters)
        {
            var idsArray = ids.ToArray();
            var totalIds = ids.Count();
            for (int i = 0; i < dataConverters.Length; i++)
            {
                var dataConverter = dataConverters[i];
                if (i < totalIds)
                {
                    var id = idsArray[i];
                    dataConverter.MigrateOneRecord(id);
                }
                else
                    dataConverter.Migrate();
            }
        }

        protected virtual void ConvertData(int id, IDataConverter dataConverter)
        {
            if (dataConverter != null)
            {
                dataConverter.MigrateOneRecord(id);
            }
        }

        protected virtual void ConvertData(IEnumerable<int>ids, IDataConverter dataConverter)
        {
            if (dataConverter != null && ids != null)
            {
                dataConverter.MigrateManyRecords(ids);
            }
        }

        protected virtual void DeleteConvertedData(int id, IDataConverter dataConverter)
        {
            if (dataConverter != null)
            {
                dataConverter.RemoveOneRecord(id);
            }
        }

        /// <summary>
        /// Check whether the scheduler has been paused by outside process
        /// </summary>
        /// <returns></returns>
        protected virtual bool ShouldExecute()
        {
            using (var repo = new ScheduledJobRepository())
            {
                var job = repo.Single(j => j.LinkConfigGuid == LinkConfig.Guid);
                if (job != null)
                {
                    return job.CrawlStatus != CrawlStatus.Paused && job.IsEnabled;
                }

                return false;
            }
        }
    }
}